package services

import (
	"fmt"
	"math/rand"
	"net/http"
	"strconv"
	"time"

	"hg/models"
	"hg/pkg/notice"
	"hg/utils"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
)

var codeMap = make(map[string]codeInfo)

type codeInfo struct {
	Code     int
	ExpireAt time.Time
}

func SendEmailCode(c *gin.Context) {
	code := getVerificationCode()
	resp := models.GetDefaultResp()
	user := getUserInfo(c)
	noticeMsg := &models.NoticeMsg{
		Title:    "验证码",
		Content:  "【沙漏视频】验证码为：" + strconv.Itoa(code),
		UserNums: []string{user.Email},
		Type:     "email",
	}
	err := notice.SendNoticeToUser(noticeMsg)
	if err != nil {
		logrus.Errorln("failed to send notice to user")
		return
	}
	// saveCodeInMemory(user.Username, code)
	saveCodeInRedis(user.Username, code)
	c.JSON(http.StatusOK, resp)
}

// func CheckCodes(username string, code int) bool {
// 	if info, exists := codeMap[username]; exists {
// 		now := time.Now()
// 		if now.After(info.ExpireAt) {
// 			delete(codeMap, username)
// 			return info.Code == code
// 		}
// 		return true
// 	}
// 	return false
// }

func getVerificationCode() int {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	code := r.Intn(900000) + 100000
	return code
}

// func saveCodeInMemory(username string, code int) {
// 	expireAt := time.Now().Add(5 * time.Minute)
// 	codeMap[username] = codeInfo{
// 		Code:     code,
// 		ExpireAt: expireAt,
// 	}
// }

func saveCodeInRedis(username string, code int) {
	client:=utils.GetRedis()
	expireAt := time.Now().Add(5 * time.Minute)
	err := client.HSet("codeMap", username, fmt.Sprintf("%d:%d", code, expireAt.Unix())).Err()
	if err != nil {
		logrus.Errorln("Failed to save code in Redis: ", err)
		return
	}
}

func getCodeFromRedis(username string) (codeInfo, error) {
	// 使用 HGET 命令从名为 "codeMap" 的 Redis 哈希中获取数据
	client:=utils.GetRedis()
	result, err := client.HGet("codeMap", username).Result()
	if err != nil {
		return codeInfo{}, err
	}

	// 解析结果字符串
	var code int
	var expireAtUnix int64
	n, err := fmt.Sscanf(result, "%d:%d", &code, &expireAtUnix)
	if err != nil || n != 2 {
		return codeInfo{}, fmt.Errorf("failed to parse code from Redis")
	}

	expireAt := time.Unix(expireAtUnix, 0)
	return codeInfo{Code: code, ExpireAt: expireAt}, nil
}

func CheckCodes(username string, code int) bool {
	info, err := getCodeFromRedis(username)
	if err != nil {
		logrus.Errorln("Failed to get code from Redis: ", err)
		return false
	}

	now := time.Now()
	if now.After(info.ExpireAt) {
		// 验证码过期，删除 Redis 中的数据
		client:=utils.GetRedis()
		err := client.HDel("codeMap", username).Err()
		if err != nil {
			logrus.Errorln("Failed to delete expired code from Redis: ", err)
		}
		return false
	}

	return info.Code == code
}